🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / app / src / main / java / com / geeksville / mesh / service / MeshServiceNotifications.kt
Displaying Raw • Download
app/src/main/java/com/geeksville/mesh/service/MeshServiceNotifications.kt ui_message_list (be3f882f) Text, 17.86 KB
T8b949e/*
* Copyright (c) 2025 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787com.geeksville.mesh.service
Tff7b72import T7ee787android.app.Notification
Tff7b72import T7ee787android.app.NotificationChannel
Tff7b72import T7ee787android.app.NotificationManager
Tff7b72import T7ee787android.app.PendingIntent
Tff7b72import T7ee787android.app.TaskStackBuilder
Tff7b72import T7ee787android.content.ContentResolver
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787android.graphics.Color
Tff7b72import T7ee787android.media.AudioAttributes
Tff7b72import T7ee787android.media.RingtoneManager
Tff7b72import T7ee787androidx.annotation.StringRes
Tff7b72import T7ee787androidx.core.app.NotificationCompat
Tff7b72import T7ee787androidx.core.app.Person
Tff7b72import T7ee787androidx.core.app.RemoteInput
Tff7b72import T7ee787androidx.core.content.getSystemService
Tff7b72import T7ee787androidx.core.net.toUri
Tff7b72import T7ee787com.geeksville.mesh.MainActivity
Tff7b72import T7ee787com.geeksville.mesh.MeshProtos
Tff7b72import T7ee787com.geeksville.mesh.R
Tff7b72import T7ee787com.geeksville.mesh.TelemetryProtos.LocalStats
Tff7b72import T7ee787com.geeksville.mesh.database.entity.NodeEntity
Tff7b72import T7ee787com.geeksville.mesh.navigation.DEEP_LINK_BASE_URI
Tff7b72import T7ee787com.geeksville.mesh.service.ReplyReceiver.Companion.KEY_TEXT_REPLY
Tff7b72import T7ee787com.geeksville.mesh.util.formatUptime
T8b949e/**
* Manages the creation and display of all app notifications.
*
* This class centralizes notification logic, including channel creation, builder configuration, and displaying
* notifications for various events like new messages, alerts, and service status changes.
*/
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4)
Tff7b72class T56d364MeshServiceNotificationsTb4b4b4(Tff7b72private Tff7b72val Te6edf3contextTb4b4b4: Te6edf3ContextTb4b4b4) Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3notificationManager Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getSystemServiceTff7b72<Te6edf3NotificationManagerTff7b72>Tb4b4b4(Tb4b4b4)Tff7b72!!
Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72private Tff7b72const Tff7b72val Te6edf3FIFTEEN_MINUTES_IN_MILLIS Tff7b72= T79c0ff1T79c0ff5L Tff7b72* T79c0ff6T79c0ff0 Tff7b72* T79c0ff1T79c0ff0T79c0ff0T79c0ff0
Tff7b72const Tff7b72val Te6edf3MAX_BATTERY_LEVEL Tff7b72= T79c0ff1T79c0ff0T79c0ff0
Tff7b72const Tff7b72val Te6edf3SERVICE_NOTIFY_ID Tff7b72= T79c0ff1T79c0ff0T79c0ff1
Tff7b72private Tff7b72val Te6edf3NOTIFICATION_LIGHT_COLOR Tff7b72= Te6edf3ColorTb4b4b4.Te6edf3BLUE
Tb4b4b4}
T8b949e/**
* Sealed class to define the properties of each notification channel. This centralizes channel configuration and
* makes it type-safe.
*/
Tff7b72private Tff7b72sealed Tff7b72class T56d364NotificationTypeTb4b4b4(
Tff7b72val Te6edf3channelIdTb4b4b4: Tffa657StringTb4b4b4,
Tf0883e@StringRes Tff7b72val Te6edf3channelNameResTb4b4b4: Tffa657IntTb4b4b4,
Tff7b72val Te6edf3importanceTb4b4b4: Tffa657IntTb4b4b4,
Tb4b4b4) Tb4b4b4{
Tff7b72object T56d364ServiceState Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Ta5d6ff"Ta5d6ffmy_serviceTa5d6ff"Tb4b4b4,
Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_service_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_MINTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364DirectMessage Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Ta5d6ff"Ta5d6ffmy_messagesTa5d6ff"Tb4b4b4,
Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_messages_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_HIGHTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364BroadcastMessage Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Ta5d6ff"Ta5d6ffmy_broadcastsTa5d6ff"Tb4b4b4,
Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_broadcast_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364Alert Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Ta5d6ff"Ta5d6ffmy_alertsTa5d6ff"Tb4b4b4,
Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_alerts_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_HIGHTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364NewNode Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Ta5d6ff"Ta5d6ffnew_nodesTa5d6ff"Tb4b4b4,
Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_new_nodes_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364LowBatteryLocal Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Ta5d6ff"Ta5d6fflow_batteryTa5d6ff"Tb4b4b4,
Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_low_battery_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364LowBatteryRemote Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(
Ta5d6ff"Ta5d6fflow_battery_remoteTa5d6ff"Tb4b4b4,
Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_low_battery_temporary_remote_notificationsTb4b4b4,
Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72object T56d364Client Tb4b4b4:
Te6edf3NotificationTypeTb4b4b4(Ta5d6ff"Ta5d6ffclient_notificationsTa5d6ff"Tb4b4b4, Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3client_notificationTb4b4b4, Te6edf3NotificationManagerTb4b4b4.Te6edf3IMPORTANCE_HIGHTb4b4b4)
Tff7b72companion Tff7b72object Tb4b4b4{
T8b949e// A list of all types for easy initialization.
Tff7b72fun Td2a8ffallTypesTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3listOfTb4b4b4(
Te6edf3ServiceStateTb4b4b4,
Te6edf3DirectMessageTb4b4b4,
Te6edf3BroadcastMessageTb4b4b4,
Te6edf3AlertTb4b4b4,
Te6edf3NewNodeTb4b4b4,
Te6edf3LowBatteryLocalTb4b4b4,
Te6edf3LowBatteryRemoteTb4b4b4,
Te6edf3ClientTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72fun Td2a8ffclearNotificationsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelAllTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e/**
* Creates all necessary notification channels on devices running Android O or newer. This should be called once
* when the service is created.
*/
Tff7b72fun Td2a8ffinitChannelsTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3NotificationTypeTb4b4b4.Te6edf3allTypesTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3type Tff7b72-Tff7b72> Te6edf3createNotificationChannelTb4b4b4(Te6edf3typeTb4b4b4) Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateNotificationChannelTb4b4b4(Te6edf3typeTb4b4b4: Te6edf3NotificationTypeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3notificationManagerTb4b4b4.Te6edf3getNotificationChannelTb4b4b4(Te6edf3typeTb4b4b4.Te6edf3channelIdTb4b4b4) Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tff7b72return
Tff7b72val Te6edf3channelName Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getStringTb4b4b4(Te6edf3typeTb4b4b4.Te6edf3channelNameResTb4b4b4)
Tff7b72val Te6edf3channel Tff7b72=
Te6edf3NotificationChannelTb4b4b4(Te6edf3typeTb4b4b4.Te6edf3channelIdTb4b4b4, Te6edf3channelNameTb4b4b4, Te6edf3typeTb4b4b4.Te6edf3importanceTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3lightColor Tff7b72= Te6edf3NOTIFICATION_LIGHT_COLOR
Te6edf3lockscreenVisibility Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3VISIBILITY_PUBLIC T8b949e// Default, can be overridden
T8b949e// Type-specific configurations
Tff7b72when Tb4b4b4(Te6edf3typeTb4b4b4) Tb4b4b4{
Te6edf3NotificationTypeTb4b4b4.Te6edf3ServiceState Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3lockscreenVisibility Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3VISIBILITY_PRIVATE
Tb4b4b4}
Te6edf3NotificationTypeTb4b4b4.Te6edf3DirectMessageTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3BroadcastMessageTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3NewNodeTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryLocalTb4b4b4,
Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryRemoteTb4b4b4,
Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3setShowBadgeTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3setSoundTb4b4b4(
Te6edf3RingtoneManagerTb4b4b4.Te6edf3getDefaultUriTb4b4b4(Te6edf3RingtoneManagerTb4b4b4.Te6edf3TYPE_NOTIFICATIONTb4b4b4)Tb4b4b4,
Te6edf3AudioAttributesTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3setUsageTb4b4b4(Te6edf3AudioAttributesTb4b4b4.Te6edf3USAGE_NOTIFICATIONTb4b4b4)
Tb4b4b4.Te6edf3setContentTypeTb4b4b4(Te6edf3AudioAttributesTb4b4b4.Te6edf3CONTENT_TYPE_SONIFICATIONTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3type Tff7b72=Tff7b72= Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryRemoteTb4b4b4) Te6edf3enableVibrationTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Te6edf3NotificationTypeTb4b4b4.Te6edf3Alert Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3setShowBadgeTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3enableLightsTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3enableVibrationTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3setBypassDndTb4b4b4(Tff7b72trueTb4b4b4)
Tff7b72val Te6edf3alertSoundUri Tff7b72=
Ta5d6ff"Tffd700${Te6edf3ContentResolverTb4b4b4.Te6edf3SCHEME_ANDROID_RESOURCETffd700}Ta5d6ff://Tffd700${Te6edf3contextTb4b4b4.Te6edf3packageNameTffd700}Ta5d6ff/Tffd700${Te6edf3RTb4b4b4.Te6edf3rawTb4b4b4.Te6edf3alertTffd700}Ta5d6ff"Tb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)
Te6edf3setSoundTb4b4b4(
Te6edf3alertSoundUriTb4b4b4,
Te6edf3AudioAttributesTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3setUsageTb4b4b4(Te6edf3AudioAttributesTb4b4b4.Te6edf3USAGE_ALARMTb4b4b4) T8b949e// More appropriate for an alert
Tb4b4b4.Te6edf3setContentTypeTb4b4b4(Te6edf3AudioAttributesTb4b4b4.Te6edf3CONTENT_TYPE_SONIFICATIONTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Te6edf3NotificationTypeTb4b4b4.Te6edf3Client Tff7b72-Tff7b72> Tb4b4b4{
Te6edf3setShowBadgeTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3notificationManagerTb4b4b4.Te6edf3createNotificationChannelTb4b4b4(Te6edf3channelTb4b4b4)
Tb4b4b4}
T8b949e// region Public Notification Methods
Tff7b72fun Td2a8ffupdateServiceStateNotificationTb4b4b4(
Te6edf3summaryStringTb4b4b4: Tffa657String?Tb4b4b4,
Te6edf3localStatsTb4b4b4: Te6edf3LocalStats? Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3currentStatsUpdatedAtMillisTb4b4b4: Tffa657Long? Tff7b72= Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72=
Te6edf3createServiceStateNotificationTb4b4b4(
Te6edf3name Tff7b72= Te6edf3summaryStringTb4b4b4.Te6edf3orEmptyTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3message Tff7b72= Te6edf3localStatsTb4b4b4.Te6edf3formatToStringTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3nextUpdateAt Tff7b72= Te6edf3currentStatsUpdatedAtMillisTff7b72?.Te6edf3plusTb4b4b4(Te6edf3FIFTEEN_MINUTES_IN_MILLISTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3SERVICE_NOTIFY_IDTb4b4b4, Te6edf3notificationTb4b4b4)
Tff7b72return Te6edf3notification
Tb4b4b4}
Tff7b72fun Td2a8ffupdateMessageNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4, Te6edf3isBroadcastTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72= Te6edf3createMessageNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3messageTb4b4b4, Te6edf3isBroadcastTb4b4b4)
T8b949e// Use a consistent, unique ID for each message conversation.
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffshowAlertNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3alertTb4b4b4: Tffa657StringTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72= Te6edf3createAlertNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4, Te6edf3nameTb4b4b4, Te6edf3alertTb4b4b4)
T8b949e// Use a consistent, unique ID for each alert source.
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3nameTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffshowNewNodeSeenNotificationTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeEntityTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72= Te6edf3createNewNodeSeenNotificationTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3shortNameTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3longNameTb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffshowOrUpdateLowBatteryNotificationTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeEntityTb4b4b4, Te6edf3isRemoteTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72= Te6edf3createLowBatteryNotificationTb4b4b4(Te6edf3nodeTb4b4b4, Te6edf3isRemoteTb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffshowClientNotificationTb4b4b4(Te6edf3clientNotificationTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3ClientNotificationTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3notification Tff7b72=
Te6edf3createClientNotificationTb4b4b4(Te6edf3contextTb4b4b4.Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3client_notificationTb4b4b4)Tb4b4b4, Te6edf3clientNotificationTb4b4b4.Te6edf3messageTb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3clientNotificationTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3notificationTb4b4b4)
Tb4b4b4}
Tff7b72fun Td2a8ffcancelMessageNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4) Tff7b72= Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72fun Td2a8ffcancelLowBatteryNotificationTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeEntityTb4b4b4) Tff7b72= Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3numTb4b4b4)
Tff7b72fun Td2a8ffclearClientNotificationTb4b4b4(Te6edf3notificationTb4b4b4: Te6edf3MeshProtosTb4b4b4.Te6edf3ClientNotificationTb4b4b4) Tff7b72=
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3notificationTb4b4b4.Te6edf3toStringTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4)
T8b949e// endregion
T8b949e// region Notification Creation
Tff7b72private Tff7b72fun Td2a8ffcreateServiceStateNotificationTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3messageTb4b4b4: Tffa657String?Tb4b4b4, Te6edf3nextUpdateAtTb4b4b4: Tffa657Long?Tb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3builder Tff7b72=
Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3ServiceStateTb4b4b4)
Tb4b4b4.Te6edf3setPriorityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3PRIORITY_MINTb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_SERVICETb4b4b4)
Tb4b4b4.Te6edf3setOngoingTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3nameTb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3messageTff7b72?.Te6edf3let Tb4b4b4{
Te6edf3builderTb4b4b4.Te6edf3setContentTextTb4b4b4(Tffa657itTb4b4b4)
Te6edf3builderTb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3BigTextStyleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3bigTextTb4b4b4(Tffa657itTb4b4b4)Tb4b4b4)
Tb4b4b4}
Te6edf3nextUpdateAtTff7b72?.Te6edf3let Tb4b4b4{
Te6edf3builderTb4b4b4.Te6edf3setWhenTb4b4b4(Tffa657itTb4b4b4)
Te6edf3builderTb4b4b4.Te6edf3setUsesChronometerTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3builderTb4b4b4.Te6edf3setChronometerCountDownTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateMessageNotificationTb4b4b4(
Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3messageTb4b4b4: Tffa657StringTb4b4b4,
Te6edf3isBroadcastTb4b4b4: Tffa657BooleanTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3type Tff7b72= Tff7b72if Tb4b4b4(Te6edf3isBroadcastTb4b4b4) Te6edf3NotificationTypeTb4b4b4.Te6edf3BroadcastMessage Tff7b72else Te6edf3NotificationTypeTb4b4b4.Te6edf3DirectMessage
Tff7b72val Te6edf3builder Tff7b72= Te6edf3commonBuilderTb4b4b4(Te6edf3typeTb4b4b4, Te6edf3createOpenMessageIntentTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3person Tff7b72= Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3style Tff7b72= Te6edf3NotificationCompatTb4b4b4.Te6edf3MessagingStyleTb4b4b4(Te6edf3personTb4b4b4)Tb4b4b4.Te6edf3addMessageTb4b4b4(Te6edf3messageTb4b4b4, Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3personTb4b4b4)
Te6edf3builder
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_MESSAGETb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3styleTb4b4b4)
Tb4b4b4.Te6edf3setVisibilityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3VISIBILITY_PRIVATETb4b4b4)
Tb4b4b4.Te6edf3setWhenTb4b4b4(Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
T8b949e// Only add reply action for direct messages, not broadcasts
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3isBroadcastTb4b4b4) Tb4b4b4{
Te6edf3builderTb4b4b4.Te6edf3addActionTb4b4b4(Te6edf3createReplyActionTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateAlertNotificationTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4, Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3alertTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3person Tff7b72= Te6edf3PersonTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setNameTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3style Tff7b72= Te6edf3NotificationCompatTb4b4b4.Te6edf3MessagingStyleTb4b4b4(Te6edf3personTb4b4b4)Tb4b4b4.Te6edf3addMessageTb4b4b4(Te6edf3alertTb4b4b4, Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3personTb4b4b4)
Tff7b72return Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3AlertTb4b4b4, Te6edf3createOpenMessageIntentTb4b4b4(Te6edf3contactKeyTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setPriorityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3PRIORITY_HIGHTb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_ALARMTb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3styleTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateNewNodeSeenNotificationTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3messageTb4b4b4: Tffa657String?Tb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3title Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3new_node_seenTb4b4b4)Tb4b4b4.Te6edf3formatTb4b4b4(Te6edf3nameTb4b4b4)
Tff7b72val Te6edf3builder Tff7b72=
Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3NewNodeTb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_STATUSTb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3titleTb4b4b4)
Tb4b4b4.Te6edf3setWhenTb4b4b4(Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
Te6edf3messageTff7b72?.Te6edf3let Tb4b4b4{
Te6edf3builderTb4b4b4.Te6edf3setContentTextTb4b4b4(Tffa657itTb4b4b4)
Te6edf3builderTb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3BigTextStyleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3bigTextTb4b4b4(Tffa657itTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tff7b72return Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateLowBatteryNotificationTb4b4b4(Te6edf3nodeTb4b4b4: Te6edf3NodeEntityTb4b4b4, Te6edf3isRemoteTb4b4b4: Tffa657BooleanTb4b4b4)Tb4b4b4: Te6edf3Notification Tb4b4b4{
Tff7b72val Te6edf3type Tff7b72= Tff7b72if Tb4b4b4(Te6edf3isRemoteTb4b4b4) Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryRemote Tff7b72else Te6edf3NotificationTypeTb4b4b4.Te6edf3LowBatteryLocal
Tff7b72val Te6edf3title Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3low_battery_titleTb4b4b4)Tb4b4b4.Te6edf3formatTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3shortNameTb4b4b4)
Tff7b72val Te6edf3message Tff7b72=
Te6edf3contextTb4b4b4.Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3low_battery_messageTb4b4b4)Tb4b4b4.Te6edf3formatTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3longNameTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3deviceMetricsTb4b4b4.Te6edf3batteryLevelTb4b4b4)
Tff7b72return Te6edf3commonBuilderTb4b4b4(Te6edf3typeTb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_STATUSTb4b4b4)
Tb4b4b4.Te6edf3setOngoingTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setOnlyAlertOnceTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setProgressTb4b4b4(Te6edf3MAX_BATTERY_LEVELTb4b4b4, Te6edf3nodeTb4b4b4.Te6edf3deviceMetricsTb4b4b4.Te6edf3batteryLevelTb4b4b4, Tff7b72falseTb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3titleTb4b4b4)
Tb4b4b4.Te6edf3setContentTextTb4b4b4(Te6edf3messageTb4b4b4)
Tb4b4b4.Te6edf3setStyleTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3BigTextStyleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3bigTextTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setWhenTb4b4b4(Te6edf3SystemTb4b4b4.Te6edf3currentTimeMillisTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4.Te6edf3setShowWhenTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateClientNotificationTb4b4b4(Te6edf3nameTb4b4b4: Tffa657StringTb4b4b4, Te6edf3messageTb4b4b4: Tffa657String?Tb4b4b4)Tb4b4b4: Te6edf3Notification Tff7b72=
Te6edf3commonBuilderTb4b4b4(Te6edf3NotificationTypeTb4b4b4.Te6edf3ClientTb4b4b4)
Tb4b4b4.Te6edf3setCategoryTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CATEGORY_ERRORTb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3nameTb4b4b4)
Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3messageTff7b72?.Te6edf3let Tb4b4b4{
Te6edf3setContentTextTb4b4b4(Tffa657itTb4b4b4)
Te6edf3setStyleTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3BigTextStyleTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3bigTextTb4b4b4(Tffa657itTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
T8b949e// endregion
T8b949e// region Helper/Builder Methods
Tff7b72private Tff7b72val Te6edf3openAppIntentTb4b4b4: Te6edf3PendingIntent Tff7b72by Te6edf3lazy Tb4b4b4{
Tff7b72val Te6edf3intent Tff7b72= Te6edf3IntentTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3MainActivityTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{ Te6edf3flags Tff7b72= Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_SINGLE_TOP Tb4b4b4}
Te6edf3PendingIntentTb4b4b4.Te6edf3getActivityTb4b4b4(Te6edf3contextTb4b4b4, T79c0ff0Tb4b4b4, Te6edf3intentTb4b4b4, Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateOpenMessageIntentTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3PendingIntent Tb4b4b4{
Tff7b72val Te6edf3deepLinkUri Tff7b72= Ta5d6ff"Tffd700$Te6edf3DEEP_LINK_BASE_URITa5d6ff/messages/Tffd700$Te6edf3contactKeyTa5d6ff"Tb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3deepLinkIntent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_VIEWTb4b4b4, Te6edf3deepLinkUriTb4b4b4, Te6edf3contextTb4b4b4, Te6edf3MainActivityTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3flags Tff7b72= Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_SINGLE_TOP
Tb4b4b4}
Tff7b72return Te6edf3TaskStackBuilderTb4b4b4.Te6edf3createTb4b4b4(Te6edf3contextTb4b4b4)Tb4b4b4.Te6edf3run Tb4b4b4{
Te6edf3addNextIntentWithParentStackTb4b4b4(Te6edf3deepLinkIntentTb4b4b4)
Te6edf3getPendingIntentTb4b4b4(Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateReplyActionTb4b4b4(Te6edf3contactKeyTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3NotificationCompatTb4b4b4.Te6edf3Action Tb4b4b4{
Tff7b72val Te6edf3replyLabel Tff7b72= Te6edf3contextTb4b4b4.Te6edf3getStringTb4b4b4(Te6edf3RTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3replyTb4b4b4)
Tff7b72val Te6edf3remoteInput Tff7b72= Te6edf3RemoteInputTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3KEY_TEXT_REPLYTb4b4b4)Tb4b4b4.Te6edf3setLabelTb4b4b4(Te6edf3replyLabelTb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3replyIntent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3ReplyReceiverTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3action Tff7b72= Te6edf3ReplyReceiverTb4b4b4.Te6edf3REPLY_ACTION
Te6edf3putExtraTb4b4b4(Te6edf3ReplyReceiverTb4b4b4.Te6edf3CONTACT_KEYTb4b4b4, Te6edf3contactKeyTb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3replyPendingIntent Tff7b72=
Te6edf3PendingIntentTb4b4b4.Te6edf3getBroadcastTb4b4b4(
Te6edf3contextTb4b4b4,
Te6edf3contactKeyTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3replyIntentTb4b4b4,
Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_MUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3NotificationCompatTb4b4b4.Te6edf3ActionTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3androidTb4b4b4.Te6edf3RTb4b4b4.Te6edf3drawableTb4b4b4.Te6edf3ic_menu_sendTb4b4b4, Te6edf3replyLabelTb4b4b4, Te6edf3replyPendingIntentTb4b4b4)
Tb4b4b4.Te6edf3addRemoteInputTb4b4b4(Te6edf3remoteInputTb4b4b4)
Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcommonBuilderTb4b4b4(
Te6edf3typeTb4b4b4: Te6edf3NotificationTypeTb4b4b4,
Te6edf3contentIntentTb4b4b4: Te6edf3PendingIntent? Tff7b72= Tff7b72nullTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3NotificationCompatTb4b4b4.Te6edf3Builder Tb4b4b4{
Tff7b72val Te6edf3smallIcon Tff7b72= Te6edf3RTb4b4b4.Te6edf3drawableTb4b4b4.Te6edf3app_icon
Tff7b72return Te6edf3NotificationCompatTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3typeTb4b4b4.Te6edf3channelIdTb4b4b4)
Tb4b4b4.Te6edf3setSmallIconTb4b4b4(Te6edf3smallIconTb4b4b4)
Tb4b4b4.Te6edf3setColorTb4b4b4(Te6edf3NOTIFICATION_LIGHT_COLORTb4b4b4)
Tb4b4b4.Te6edf3setVisibilityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3VISIBILITY_PUBLICTb4b4b4)
Tb4b4b4.Te6edf3setContentIntentTb4b4b4(Te6edf3contentIntent Tff7b72?: Te6edf3openAppIntentTb4b4b4)
Tb4b4b4}
T8b949e// endregion
Tb4b4b4}
T8b949e// Extension function to format LocalStats into a readable string.
Tff7b72private Tff7b72fun Td2a8ffLocalStatsTff7b72?.Te6edf3formatToStringTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72this Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tff7b72return Ta5d6ff"Ta5d6ffNo Local StatsTa5d6ff"
Tff7b72return Tff7b72thisTb4b4b4.Te6edf3allFields
Tb4b4b4.Te6edf3mapNotNull Tb4b4b4{ Tb4b4b4(Te6edf3kTb4b4b4, Te6edf3vTb4b4b4) Tff7b72-Tff7b72>
Tff7b72when Tb4b4b4(Te6edf3kTb4b4b4.Te6edf3nameTb4b4b4) Tb4b4b4{
Ta5d6ff"Ta5d6ffnum_online_nodesTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffnum_total_nodesTa5d6ff"Tb4b4b4,
Tff7b72-Tff7b72> Tff7b72null T8b949e// Exclude these fields
Ta5d6ff"Ta5d6ffuptime_secondsTa5d6ff" Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffUptime: Tffd700${Te6edf3formatUptimeTb4b4b4(Te6edf3v Tff7b72as Tffa657IntTb4b4b4)Tffd700}Ta5d6ff"
Ta5d6ff"Ta5d6ffchannel_utilizationTa5d6ff" Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffChUtil: %.2f%%Ta5d6ff"Tb4b4b4.Te6edf3formatTb4b4b4(Te6edf3vTb4b4b4)
Ta5d6ff"Ta5d6ffair_util_txTa5d6ff" Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffAirUtilTX: %.2f%%Ta5d6ff"Tb4b4b4.Te6edf3formatTb4b4b4(Te6edf3vTb4b4b4)
Tff7b72else Tff7b72-Tff7b72> Tb4b4b4{
Tff7b72val Te6edf3formattedKey Tff7b72= Te6edf3kTb4b4b4.Te6edf3nameTb4b4b4.Te6edf3replaceTb4b4b4(Ta5d6ff'_'Tb4b4b4, Ta5d6ff' 'Tb4b4b4)Tb4b4b4.Te6edf3replaceFirstChar Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3titlecaseTb4b4b4(Tb4b4b4) Tb4b4b4}
Ta5d6ff"Tffd700$Te6edf3formattedKeyTa5d6ff: Tffd700$Te6edf3vTa5d6ff"
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4.Te6edf3joinToStringTb4b4b4(Ta5d6ff"Ta5d6ff\Ta5d6ffnTa5d6ff"Tb4b4b4)
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.11s